import React from 'react';
import { withPropsAPI, Flow } from 'gg-editor';
import styles from './index.less';
import './index.less';
import CodeMirror from 'react-codemirror';
import 'codemirror/lib/codemirror.css';
import 'codemirror/mode/javascript/javascript';
import { Modal } from 'antd';
import ServiceTaskNode from './ServiceTaskNode.js';

const nodeIndexes = {
  Start: 1,
  ServiceTask: 1,
  ScriptTask: 1,
  Compensation: 1,
  Choice: 1,
  Succeed: 1,
  Fail: 1,
  Catch: 1,
  CompensationTrigger: 1,
  SubStateMachine: 1,
};

/**
 * 画布区域
 */
class WorkSpaceBase extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      visible: false,
      currentItemType: '',
      num: 0,
    };
  }
  componentDidMount() {
    this.bindEvent();
  }

  // 绑定点击事件
  bindEvent() {
    console.log(this.props.propsAPI.editor.getCurrentPage());
    this.props.propsAPI.editor
      .getCurrentPage()
      .on('node:dblclick', ({ item }) => {
        // item是当前点击的节点
        console.log(item.getModel());

        const { stateType } = item.getModel();

        this.setState({
          visible: true,
          currentItemType: stateType,
        });
      });
  }

  //调用子组件方法
  onRef = (ref) => {
    this.state.num++;
    this.child = ref;
  };

  /**
   * 提交修改表单
   * 触发节点属性改变
   */
  handleOk = () => {
    this.child.changeFlowData();
    //调用子组件方法改变数据状态
    if (this.state.currentItemType !== 'Start') {
      console.log(this.child.changeFlowData());
      this.child.changeFlowData();
    }

    this.setState({
      visible: false,
    });
  };

  handleCancel = () => {
    this.setState({
      visible: false,
    });
  };

  toGGEditorData(dataMap) {
    const data = { nodes: [], edges: [] };
    Object.values(dataMap).map((value) => {
      if (value.type && value.type == 'node') {
        data.nodes[data.nodes.length] = value;
      } else if (value.source && value.target) {
        data.edges[data.edges.length] = value;
      }
    });
    return data;
  }

  changeFlowData(param) {
    const { propsAPI, setFlowData } = this.props;
    const { executeCommand, update } = propsAPI;

    if (param.action == 'add' && param.item.type == 'edge') {
      // Default polyline-round type @FIXME polyline-round has a bug
      if (
        param.item.target &&
        param.item.target.model &&
        param.item.source &&
        param.item.source.model
      ) {
        executeCommand(() => {
          update(param.item, {
            shape: 'flow-polyline-round',
          });
        });
      }
      if (
        param.item.target &&
        param.item.target.model &&
        param.item.target.model.stateType == 'Compensation'
      ) {
        executeCommand(() => {
          update(param.item, {
            style: {
              lineDash: '4',
            },
            type: 'Compensation',
          });
        });
      } else if (param.item.source && param.item.source.model) {
        if (param.item.source.model.stateType == 'Choice') {
          const choiceLinePropsTemplate = {
            Expression: '',
            Default: false,
          };
          executeCommand(() => {
            update(param.item, {
              stateProps: choiceLinePropsTemplate,
            });
          });
        } else if (param.item.source.model.stateType == 'Catch') {
          const catchLinePropsTemplate = {
            Exceptions: ['java.lang.Throwable'],
          };
          executeCommand(() => {
            update(param.item, {
              stateProps: catchLinePropsTemplate,
            });
          });
        }
      }
    }

    if (
      param.action == 'add' &&
      param.item.type == 'node' &&
      param.item.model
    ) {
      param.item.model.stateId =
        param.item.model.stateId + nodeIndexes[param.item.model.stateType]++;
      if (
        param.item.model.stateType == 'ServiceTask' ||
        param.item.model.stateType == 'Compensation' ||
        param.item.model.stateType == 'ScriptTask' ||
        param.item.model.stateType == 'SubStateMachine'
      ) {
        param.item.model.label = param.item.model.stateId;
      }
      if (param.item.model.stateType == 'SubStateMachine') {
        executeCommand(() => {
          update(param.item, {
            style: {
              lineWidth: 2,
            },
          });
        });
      }
    }

    param.item && setFlowData(this.toGGEditorData(param.item.dataMap));
  }

  render() {
    const { showJson, flowData, setFlowData } = this.props;

    return (
      <>
        {showJson && (
          <CodeMirror
            value={JSON.stringify(flowData, null, 2)}
            options={{
              lineNumbers: true,
              mode: 'javascript',
            }}
            onChange={(newValue) => {
              setFlowData(JSON.parse(newValue));
            }}
          ></CodeMirror>
        )}
        <Flow
          className={styles.flow + (showJson ? ' ' + styles.hidden : '')}
          data={flowData}
          onAfterChange={this.changeFlowData.bind(this)}
        />
        <Modal
          visible={this.state.visible}
          onOk={this.handleOk}
          onCancel={this.handleCancel}
          key={this.state.num}
          className="buttonModal"
        >
          {this.state.visible &&
            this.state.currentItemType === 'ServiceTask' && (
              <ServiceTaskNode
                typeWorkSpace={'workSpaceType'}
                onRef={this.onRef}
                onClose={() => {
                  this.state.num++;
                  this.setState({
                    visible: false,
                  });
                }}
              />
            )}
          {/* {this.state.visible && this.state.currentItemType === 'Compensation' && (
            <ServiceTaskNode
              typeWorkSpace={'workSpaceType'}
              onRef={this.onRef}
              onClose={() => {
                this.state.num++;
                this.setState({
                  visible: false,
                });
              }}
            />
          )} */}
        </Modal>
      </>
    );
  }
}

// 凡是用 withPropsAPI 包裹过的组件，组件 props 中会有 propsAPI 属性
export const WorkSpace = withPropsAPI(WorkSpaceBase);
